<?php
require_once("SvnLookClasses.php");

class SVNLook {
	var $basedir="";
	var $username="";
	var $password="";

    function SVNLook($basedir, $username, $password ) {
		$this->basedir = $basedir;
		$this->username = $username;
		$this->password = $password;

        if( $basedir != FALSE ) {
            chdir( $basedir );
        }
	}

	function getSvnStatus($path=".") { 
		$result = $this->executeSvnCommand("status", $path, ''); 
		$domArray = $this->getResultXmlDom($result);

		$svnPath = $domArray->target['path'];
		$againstRev = $domArray->target->against['revision'];

		$curSVNStatus = new SVNStatus;
		$curSVNStatus->path = $svnPath;
		$curSVNStatus->againstRev = $againstRev;

		foreach($domArray->target->entry as $entry) {
			$path     = (string)$entry['path'];
			$wcStatus = (string)$entry->{'wc-status'}['item'];
			$wcStatusRev = (string)$entry->{'wc-status'}['revision'];
			$repoStatus = (string)$entry->{'repos-status'}['item'];

			#$date     = $this->getLocalTime( $entry->commit->date );
			$statusEntry = new SVNStatusEntry;
			$statusEntry->path = $path;
			$statusEntry->wcStatus = $wcStatus;
			$statusEntry->wcStatusRev = $wcStatusRev;
			$statusEntry->repoStatus = $repoStatus;

			$curSVNStatus->entries[] = $statusEntry;
		}
		
		usort($curSVNStatus->entries, "_statusSort");

		return $curSVNStatus;
	}

	function getSvnList($path=".", $revision='', $sort='', $comment=true) { 
		$result = $this->executeSvnCommand('list', $path, $revision); 
		$domArray = $this->getResultXmlDom($result);
		$svnPath = $domArray->list['path'];

		$curSVNList = new SVNList;
		#$curSVNList->entries = array();
		$curSVNList->path = $svnPath;


		foreach($domArray->list->entry as $entry) {
			$kind     = $entry['kind'];
			$name     = (string)$entry->name; 
			$author   = (string)$entry->commit->author; 
			$revision = (string)$entry->commit['revision']; 
			$path     = $svnPath.'/'.$name;
			$date     = $this->getLocalTime( $entry->commit->date );

			$listEntry = new SVNListEntry;
			$listEntry->author = $author;
			$listEntry->revision = $revision;
			$listEntry->isdir = ($kind == 'dir');
			$listEntry->name = $name;
			$listEntry->date = $date;

			if( $listEntry->isdir && $comment ) {
			    $listEntry->name .= '/';
				$listEntry->comment  = $this->getSvnLogByRevision($path, $revision);
			}

			$curSVNList->entries[] = $listEntry;
		}

        if( $sort == 'desc' ) {
		    usort($curSVNList->entries, "_listSortDesc");
        }
        else {
		    usort($curSVNList->entries, "_listSort");
        }

		return $curSVNList;
	}

	function getSvnLogByRevision($path, $revision) {
		$result = $this->executeSvnCommand('log', $path, $revision );
		$domArray = $this->getResultXmlDom($result);
		$logmsg = (string)$domArray->logentry->msg;
		if( empty($logmsg) ) {
			return '';
		}
		else {
			return $logmsg;
		}
	}

	function getSvnLogList($path, $revision) {
		if( empty( $revision ) ) {
			$revision = "HEAD";
		}
		$revision = "$revision:0";
		$addOptions = "--limit 25";

		$result = $this->executeSvnCommand('log', $path, $revision, $addOptions); 
		$domArray = $this->getResultXmlDom($result);

		$curSVNLog = new SVNLog;
		foreach($domArray->logentry as $entry) {
			$logEntry = new SVNLogEntry;
			$logEntry->revision = (string)$entry['revision']; 
			$logEntry->author   = (string)$entry->author; 
			$logEntry->date     = $this->getLocalTime( $entry->date );
			$logEntry->msg      = (string)$entry->msg;

			#echo "-- logentry : ".$logEntry->msg."\n";
			foreach($entry->paths->path as $path) {
				$logPath = new SVNLogEntryPath;
				$logPath->path		= (string)$path;
				#$logPath->action	= (string)$path['action'];
				#$logPath->copyfrom_path	= (string)$path['copyfrom-path'];
				#$logPath->copyfrom_rev	= (string)$path['copyfrom-rev'];

				#echo ">>>>>>> add : ".$logPath->path."\n";
				$logEntry->paths[] = $logPath;
			}

			$curSVNLog->entries[] = $logEntry;
		}

		#usort($curSVNList->entries, "_listSort");

		return $curSVNLog;
	}


	function executeSvnCommand($command, $path='.', $revision='', $addOptions='' ) {
		$options = "--non-interactive --username ".$this->username." --password ".$this->password;

		switch($command) {
			case "list";
				$options .= " --xml ";
			break;
			case "status";
				$options .= " -u --xml ";
			break;
			case "log";
				$options .= " -v --xml ";
			break;
			case "commit";
				$options .= " --file ";
			break;
			default;
			break;
		}

		if( $revision != '' ) {
			$options .= " -r $revision ";
		}

		#print( "<pre>svn $command $options $path</pre>" );

		$result = `svn $command $options $addOptions $path`;


		return $result;
	}

	function getResultXmlDom( $xmlString ) {
		$sxe = simplexml_load_string( $xmlString );
		if ($sxe === false) {
			return 'Error while parsing the document';
		}

		$dom = simplexml_import_dom($sxe);
		return $dom;
	}

	function getLocalTime( $gmtTime ) {
		putenv("TZ=Asia/Seoul");
		$timestamp = strtotime($gmtTime);
		$date = date("Y/m/d H:i:s", $timestamp);
		putenv("TZ=");
		return $date;
	}
}
function _listSortDesc($e1, $e2) {
    return _listSort($e2, $e1);
}

function _listSort($e1, $e2) {
	$isDir1 = $e1->name{strlen($e1->name) - 1} == "/";
	$isDir2 = $e2->name{strlen($e2->name) - 1} == "/";

	if ($isDir1 && !$isDir2) return -1;
	if ($isDir2 && !$isDir1) return 1;

	return strnatcasecmp($e1->name, $e2->name);
}

function _statusSort($e1, $e2) {
	return strnatcasecmp($e1->wcStatus, $e2->wcStatus);
}

//TEST... 
#$svn = new SVNLook("/daum/dnt/repository/agora/branches/rc/agora2-site", "agora","welcome");
#SVNLogList test
#$svnloglist = $svn->getSvnLogList();

#SVNList test
#$svnlist = $svn->getSvnList();
#print_r( $svnlist->entries );
#echo $svnlist->path;

#SVNStatus test
#$svnstatus = $svn->getSvnStatus();
#print_r( $svnstatus->entries );
#echo $svnstatus->path;
#echo $svnstatus->againstRev;
?>
